package com.example.mywike.config.shiroConfig;

import org.apache.shiro.authc.credential.CredentialsMatcher;
import org.apache.shiro.cache.CacheManager;
import org.apache.shiro.cache.MemoryConstrainedCacheManager;
import org.apache.shiro.mgt.RememberMeManager;
import org.apache.shiro.session.mgt.SessionManager;
import org.apache.shiro.spring.LifecycleBeanPostProcessor;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.CookieRememberMeManager;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.web.servlet.SimpleCookie;
import org.apache.shiro.web.session.mgt.DefaultWebSessionManager;
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.servlet.Filter;
import java.util.LinkedHashMap;
import java.util.Map;

/**
 * shiro的配置类
 * @author sujin
 *
 */
@Configuration
public class ShiroConfiguration {

    /**
     * @param userRealm 自己配置的授权对象
     * @author xiyangqilvgui
     * @decription  配置安全管理框架，shiro的核心，协调管理组件工作
     * @date 2020/9/6 20:14
     * @version 1.0.0
     * @return ShiroFilterFactoryBean
     * */
    @Bean(name="securityManager")
    public SecurityManager securityManager(@Qualifier("userRealm") UserRealm userRealm,
                                           @Qualifier("cacheManager1") CacheManager cacheManager1,
                                           @Qualifier("sessionManager") SessionManager sessionManager,
                                           @Qualifier("rememberMeManager") RememberMeManager rememberMeManager) {
        System.err.println("--------------shiro已经加载----------------");
        DefaultWebSecurityManager manager=new DefaultWebSecurityManager();
        // 注入认证的域
        manager.setRealm(userRealm);
        // 注入缓存管理器
        manager.setCacheManager(cacheManager1);
        // 注入回话配置
        manager.setSessionManager(sessionManager);
        // 注入记住我cookie管理器
        manager.setRememberMeManager(rememberMeManager);
        return manager;
    }


    /**
     * @param manager 这是shiro框架的管理器
     * @author xiyangqilvgui
     * @decription  配置拦截器
     * @date 2020/9/6 20:14
     * @version 1.0.0
     * @return ShiroFilterFactoryBean
     * */
    @Bean(name="shiroFilter")
    public ShiroFilterFactoryBean shiroFilter(@Qualifier("securityManager") SecurityManager manager,
                                              @Qualifier("myRememberFilter") Filter myRememberFilter ) {
        ShiroFilterFactoryBean shiroFilterFactoryBean=new ShiroFilterFactoryBean();
        shiroFilterFactoryBean.setSecurityManager(manager);

        Map<String, Filter> filterMap=new LinkedHashMap<>();
        filterMap.put("MyRememberFilter",myRememberFilter);

        //配置登录的url和登录成功的url
        shiroFilterFactoryBean.setLoginUrl("/login");
        shiroFilterFactoryBean.setSuccessUrl("/home");
        //配置访问权限
        Map<String, String> filterChainDefinitionMap=new LinkedHashMap<>();
        //表示可以匿名访问
        filterChainDefinitionMap.put("/login*", "anon");
        filterChainDefinitionMap.put("/logout*", "logout");
        filterChainDefinitionMap.put("/api/user/*", "anon");
        //添加白名单
        filterChainDefinitionMap.put("/assert/test", "anon");
        //添加白名单
        filterChainDefinitionMap.put("/assert/get", "anon");
        //添加白名单
        filterChainDefinitionMap.put("/assert/assertQuery", "anon");
        //表示需要认证才可以访问
        filterChainDefinitionMap.put("/**", "user");
        shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
        return shiroFilterFactoryBean;
    }

    /** 配置自定义的权限登录器 */
    /**
     * @param matcher 密码比较器
     * @author xiyangqilvgui
     * @decription 注入密码比较器，配置领域，用域认证和授权
     * @date 2020/9/12 23:28
     * @version 1.0.0
     * @return Realm 对象
     * */
    @Bean(name="userRealm")
    public UserRealm userRealm(@Qualifier("credentialsMatcher") CredentialsMatcher matcher) {
        UserRealm userRealm=new UserRealm();
        userRealm.setCredentialsMatcher(matcher);
        return userRealm;
    }


    /**
     * @author xiyangqilvgui
     * @decription 将自己写的密码比较器交给spring框架管理
     * @date 2020/9/12 22:51
     * @version 1.0.0
     * @return 密码比较对象
     * */
    @Bean(name="credentialsMatcher")
    public CredentialsMatcherMe credentialsMatcher() {
        return new CredentialsMatcherMe();
    }

    /**
     * @author xiyangqilvgui
     * @decription 配置shiro框架缓存对象
     * @date 2020/9/12 23:40
     * @version 1.0.0
     * @return
     * */
    @Bean(name = "cacheManager1")
    public CacheManager cacheManager1(){
        return new MemoryConstrainedCacheManager();
    }

    /**
     * @author xiyangqilvgui
     * @decription 前端回话时间
     * @date 2020/9/13 0:10
     * @version 1.0.0
     * @return
     * */
    @Bean(name = "sessionManager")
    public SessionManager sessionManager(){
        DefaultWebSessionManager sessionManager = new DefaultWebSessionManager();
        // 设置超时时间
        sessionManager.setGlobalSessionTimeout(ShiroConfigStingInteger.HALF_HOUR_MILLISECOND);
        // 设置会话失效
        sessionManager.setDeleteInvalidSessions(true);
        sessionManager.setSessionIdUrlRewritingEnabled(true);
        return sessionManager;
    }

    /**
     * @author xiyangqilvgui
     * @decription 设置记住我的世界周期
     * @date 2020/9/13 0:37
     * @version 1.0.0
     * @return
     * */
    public SimpleCookie rememberMeCookie() {
        // 这个参数是cookie的名称，对应前端的checkbox的name=rememberMe
        SimpleCookie simpleCookie = new SimpleCookie("rememberMe");
        // cookie生效时间为10秒
        simpleCookie.setMaxAge(ShiroConfigStingInteger.WEEK_SECOND);
        return simpleCookie;
    }

    /**
     * @author xiyangqilvgui
     * @decription shiro的“记住我”管理器
     * @date 2020/9/13 0:38
     * @version 1.0.0
     * @return
     * */
    @Bean(name = "rememberMeManager")
    public RememberMeManager rememberMeManager() {
        CookieRememberMeManager cookieRememberMeManager = new CookieRememberMeManager();
        cookieRememberMeManager.setCookie(rememberMeCookie());
        return  cookieRememberMeManager;
    }

    /**
     * @author xiyangqilvgui
     * @decription “记住我”过滤器
     * @date 2020/9/13 0:40
     * @version 1.0.0
     * */
    @Bean(name = "myRememberFilter")
    public MyRememberFilter myRememberFilter(){
        return new MyRememberFilter();
    }


    /**
     * @author xiyangqilvgui
     * @decription 配置shiro的生命周期
     * @date 2020/9/13 0:02
     * @version 1.0.0
     * */
    @Bean
    public LifecycleBeanPostProcessor lifecycleBeanPostProcessor(){
        return new LifecycleBeanPostProcessor();
    }
    /**
     * @author xiyangqilvgui
     * @decription 配置shiro注解是否生效
     * @date 2020/9/13 0:05
     * @version 1.0.0
     * */
    @Bean
    public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator(){
        DefaultAdvisorAutoProxyCreator creator=new DefaultAdvisorAutoProxyCreator();
        creator.setProxyTargetClass(true);
        return creator;
    }
    /**
     * @author xiyangqilvgui
     * @decription 授权属性的Advisor配置
     * @date 2020/9/13 0:05
     * @version 1.0.0
     * */
    @Bean
    public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(@Qualifier("securityManager")
                                                                                       SecurityManager manager) {
        AuthorizationAttributeSourceAdvisor advisor=new AuthorizationAttributeSourceAdvisor();
        advisor.setSecurityManager(manager);
        return advisor;
    }
}
